package com.qf.cx.simplenms.topic.util;

import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;

import com.qf.cx.simplenms.reader.model.AntennaModel;
import com.qf.cx.simplenms.reader.tag.Tag;
import com.qf.cx.simplenms.reader.tag.Tag.ReadOpResult;
import com.qf.cx.simplenms.report.model.Device;
import com.qf.cx.simplenms.report.model.Element;
import com.qf.cx.simplenms.report.model.Operation;
import com.qf.cx.simplenms.report.model.Report;
import com.qf.cx.simplenms.report.model.Statistic;
import com.qf.cx.simplenms.report.model.TagInfo;
import com.qf.cx.simplenms.report.model.VehicleInfo;
import com.qf.cx.simplenms.tagmemory.model.TagMemoryModel.Identifier;
import com.qf.cx.simplenms.topic.enumerate.DiscoveryType;
import com.qf.cx.simplenms.topic.enumerate.OpType;
import com.qf.cx.simplenms.topic.tag.TopicTag;

public final class ReportGenerator {
	public static Report generate(String topicName, Collection<TopicTag> tags) {
		Report report = generateHeader(topicName);
		report.setBody(generateBody(tags));
		return report;

	}

	private static Report generateHeader(String topicName) {
		Report report = new Report();
		report.setTopic(topicName);
		report.setCacheType(0);
		ZonedDateTime date = ZonedDateTime.now();
		report.setReportCreateTime(date.toInstant().toEpochMilli());
		report.setGmt(date.getOffset().toString());
		return report;
	}

	private static List<Element> generateBody(Collection<TopicTag> tags) {
		List<Element> body = new ArrayList<>();
		for (TopicTag t : tags) {
			body.add(generateElement(t));
		}
		return body;
	}

	private static Element generateElement(TopicTag t) {
		Element element = new Element();
		element.setDevice(generateDevice(t.getAntenna()));
		element.setDeviceGroupSet(t.getReaderGroupNames());
		element.setDiscoveryTime(t.getDiscoveryTime());
		element.setStatistics(statistics(t.getStatistics().values()));
		element.addDiscoveryType(DiscoveryType.CURRENT.getValue());
		element.setTagInfo(generateTagInfo(t));
		return element;
	}

	private static List<Statistic> statistics(Collection<com.qf.cx.simplenms.reader.tag.Statistic> ins) {
		List<Statistic> list = new ArrayList<>(ins.size());
		for (com.qf.cx.simplenms.reader.tag.Statistic in : ins) {
			Statistic e = new Statistic();
			e.setAnt(in.getAnt());
			e.setCount(in.getCount());
			e.setReader(in.getReader());
			list.add(e);
		}
		return list;
	}

	private static TagInfo generateTagInfo(TopicTag t) {
		TagInfo tagInfo = new TagInfo();
		tagInfo.setTID(t.getTag().getTid());
		tagInfo.setOperations(generateOperations(t.getTag()));
		tagInfo.setVehicleInfo(generateVehicleInfo(t.getTag()));
		return tagInfo;
	}

	private static VehicleInfo generateVehicleInfo(Tag tag) {
		for (com.qf.cx.simplenms.reader.tag.Tag.VehicleInfo one : tag.getVehicleInfos().values()) {
			VehicleInfo o = new VehicleInfo();
			o.setCapacity(one.getCapacity());
			o.setColor(one.getColor());
			o.setEmission(one.getEmission());
			o.setLicense(one.getLicense());
			o.setLicenseType(one.getLicenseType());
			o.setManufactureDate(one.getManufactureDate());
			o.setPower(one.getPower());
			o.setRetirementDate(one.getRetirementDate());
			o.setUsage(one.getUsage());
			o.setValidity(one.getValidity());
			o.setVehicleType(one.getVehicleType());
			return o;
		}
		return null;
	}

	private static List<Operation> generateOperations(Tag tag) {
		List<Operation> operations = new ArrayList<>();
		for (Entry<Identifier, ReadOpResult> each : tag.getReadOpResults().entrySet()) {
			Operation o = new Operation();
			o.setData(each.getValue().getData());
			o.setOpResult(each.getValue().getOpResult());
			o.setOpType(OpType.READ.getValue());
			o.setTagMemory(each.getKey().tm.name);
			operations.add(o);
		}
		return operations;
	}

	private static Device generateDevice(AntennaModel antennaModel) {
		Device device = new Device();
		device.setAntenna(antennaModel.getAntennaNo());
		device.setIp(antennaModel.getReaderModel().getIp());
		device.setProtocol(antennaModel.getProtocol());
		device.setReader(antennaModel.getReaderName());
		return device;
	}

	private ReportGenerator() {
	}
}
